```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>深入理解Java虚拟机(JVM)</title>
    <link href="https://cdn.staticfile.org/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
    <link href="https://cdn.staticfile.org/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/mermaid@latest/dist/mermaid.min.js"></script>
    <style>
        body {
            font-family: 'Noto Sans SC', Tahoma, Arial, Roboto, "Droid Sans", "Helvetica Neue", "Droid Sans Fallback", "Heiti SC", "Hiragino Sans GB", Simsun, sans-serif;
            color: #333;
            line-height: 1.6;
            background-color: #f8fafc;
        }
        .heading {
            font-family: 'Noto Serif SC', serif;
        }
        .hero {
            background: linear-gradient(135deg, #1e3a8a 0%, #2563eb 100%);
            color: white;
        }
        .card {
            transition: transform 0.3s ease, box-shadow 0.3s ease;
            border-radius: 0.5rem;
            overflow: hidden;
        }
        .card:hover {
            transform: translateY(-5px);
            box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
        }
        .code-block {
            background-color: #2d3748;
            color: #e2e8f0;
            border-radius: 0.375rem;
            overflow-x: auto;
        }
        .footer {
            background-color: #1a202c;
            color: #e2e8f0;
        }
        .diagram-container {
            background-color: white;
            border-radius: 0.5rem;
            padding: 1.5rem;
            box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
        }
        .highlight {
            position: relative;
        }
        .highlight:before {
            content: '';
            position: absolute;
            left: -4px;
            top: 0;
            height: 100%;
            width: 4px;
            background-color: #2563eb;
        }
    </style>
</head>
<body>
    <!-- Hero Section -->
    <section class="hero py-20 px-4 md:px-0">
        <div class="container mx-auto max-w-5xl text-center">
            <h1 class="heading text-4xl md:text-5xl font-bold mb-6">深入理解Java虚拟机</h1>
            <p class="text-xl md:text-2xl opacity-90 mb-8">探索JVM架构、内存模型与性能优化的奥秘</p>
            <div class="flex justify-center space-x-4">
                <a href="#basic-concepts" class="bg-white text-blue-800 px-6 py-3 rounded-lg font-medium hover:bg-blue-50 transition duration-300">核心概念</a>
                <a href="#memory-structure" class="bg-transparent border-2 border-white text-white px-6 py-3 rounded-lg font-medium hover:bg-white hover:text-blue-800 transition duration-300">内存架构</a>
            </div>
        </div>
    </section>

    <!-- Main Content -->
    <div class="container mx-auto max-w-5xl px-4 md:px-0 py-12">
        <!-- Basic Concepts Section -->
        <section id="basic-concepts" class="mb-16">
            <h2 class="heading text-3xl font-bold mb-8 text-gray-800">Java中的基本概念</h2>
            
            <div class="grid md:grid-cols-3 gap-6 mb-12">
                <!-- JDK Card -->
                <div class="card bg-white shadow-md">
                    <div class="p-6">
                        <div class="flex items-center mb-4">
                            <i class="fas fa-cube text-blue-600 text-2xl mr-3"></i>
                            <h3 class="heading text-xl font-semibold">JDK</h3>
                        </div>
                        <p class="text-gray-600 mb-4">Java SE Development Kit，Java标准开发包，它提供了编译、运行Java程序所需的各种工具和资源，包括Java编译器、Java运行时环境，以及常用的Java类库等。</p>
                        <img src="https://cdn.nlark.com/yuque/0/2022/png/21449790/1654432776188-3db62aa5-49d6-42c9-81a6-357179232769.png" alt="JDK图示" class="rounded-lg w-full">
                    </div>
                </div>
                
                <!-- JRE Card -->
                <div class="card bg-white shadow-md">
                    <div class="p-6">
                        <div class="flex items-center mb-4">
                            <i class="fas fa-box-open text-green-600 text-2xl mr-3"></i>
                            <h3 class="heading text-xl font-semibold">JRE</h3>
                        </div>
                        <p class="text-gray-600 mb-4">Java Runtime Environment，也就是我们说的JAVA平台，所有的Java程序都要在JRE下才能运行。包括JVM和JAVA核心类库和支持文件。与JDK相比，它不包含开发工具——编译器、调试器和其它工具。</p>
                        <img src="https://cdn.nlark.com/yuque/0/2022/png/21449790/1654432776560-f2682196-2774-4ab2-8f54-4f1e0230f670.png" alt="JRE图示" class="rounded-lg w-full">
                    </div>
                </div>
                
                <!-- JVM Card -->
                <div class="card bg-white shadow-md">
                    <div class="p-6">
                        <div class="flex items-center mb-4">
                            <i class="fas fa-microchip text-purple-600 text-2xl mr-3"></i>
                            <h3 class="heading text-xl font-semibold">JVM</h3>
                        </div>
                        <p class="text-gray-600 mb-4">JVM是JRE的一部分，它是一个虚构出来的计算机，是通过在实际的计算机上仿真模拟各种计算机功能来实现的。JVM有自己完善的硬件架构，如处理器、堆栈、寄存器等，还具有相应的指令系统。</p>
                    </div>
                </div>
            </div>
            
            <div class="mb-12">
                <h3 class="heading text-2xl font-semibold mb-4 text-gray-800">三者关系</h3>
                <img src="https://cdn.nlark.com/yuque/0/2022/png/21449790/1654432777049-e6937bd4-e37e-4696-b783-d5129eacde22.png" alt="JDK、JRE、JVM关系图" class="rounded-lg shadow-md w-full">
            </div>
            
            <div>
                <h3 class="heading text-2xl font-semibold mb-4 text-gray-800">Java程序执行流程</h3>
                <img src="https://cdn.nlark.com/yuque/0/2022/png/21449790/1654432777637-c6d2dbda-6c7c-4027-a7a2-23545a5fe8d4.png" alt="Java程序执行流程" class="rounded-lg shadow-md w-full">
            </div>
        </section>

        <!-- JVM Architecture Section -->
        <section id="memory-structure" class="mb-16">
            <h2 class="heading text-3xl font-bold mb-8 text-gray-800">JVM体系结构</h2>
            
            <div class="mb-12">
                <h3 class="heading text-2xl font-semibold mb-4 text-gray-800">JDK 17体系结构</h3>
                <img src="https://cdn.nlark.com/yuque/0/2022/png/21449790/1654432778013-b51cbc74-283a-4b31-aa86-b168644161c2.png" alt="JDK 17体系结构" class="rounded-lg shadow-md w-full">
                
                <div class="grid md:grid-cols-2 gap-6 mt-6">
                    <div class="highlight p-4 bg-white rounded-lg shadow">
                        <h4 class="heading text-lg font-semibold mb-3 text-gray-800">方法区</h4>
                        <p class="text-gray-600">在方法区中存储了每个类的信息（包括类的名称、方法信息、字段信息）、静态变量、常量以及编译器编译后的代码等。</p>
                    </div>
                    <div class="highlight p-4 bg-white rounded-lg shadow">
                        <h4 class="heading text-lg font-semibold mb-3 text-gray-800">虚拟机栈</h4>
                        <p class="text-gray-600">Java虚拟机栈跟程序计数器一样是线程私有的，它的生命周期和线程相同。虚拟机栈描述的是Java方法执行的内存模型：每个方法在执行时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。</p>
                    </div>
                    <div class="highlight p-4 bg-white rounded-lg shadow">
                        <h4 class="heading text-lg font-semibold mb-3 text-gray-800">本地方法栈</h4>
                        <p class="text-gray-600">本地方法栈与虚拟机栈作用相似，它们之间的区别是虚拟机栈为虚拟机执行Java方法服务，而本地方法栈则为虚拟机使用到的Native方法服务。</p>
                    </div>
                    <div class="highlight p-4 bg-white rounded-lg shadow">
                        <h4 class="heading text-lg font-semibold mb-3 text-gray-800">程序计数器</h4>
                        <p class="text-gray-600">程序计数器可以看作当前线程所执行的字节码的行号指示器。如果线程执行的是Java方法那么这个计数器记录的是正在执行的虚拟机字节码指令地址。</p>
                    </div>
                    <div class="highlight p-4 bg-white rounded-lg shadow">
                        <h4 class="heading text-lg font-semibold mb-3 text-gray-800">堆</h4>
                        <p class="text-gray-600">Java堆通常是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域，在虚拟机启动时创建。这块区域唯一的目的就是存放对象实例。</p>
                    </div>
                </div>
            </div>
            
            <div class="mb-12">
                <h3 class="heading text-2xl font-semibold mb-4 text-gray-800">1.7和1.8对比</h3>
                <img src="https://cdn.nlark.com/yuque/0/2022/png/21449790/1654432778622-478fa293-814a-4752-9bd9-1f2f987b90ea.png" alt="JDK 1.7和1.8对比" class="rounded-lg shadow-md w-full">
                
                <div class="grid md:grid-cols-2 gap-6 mt-6">
                    <div class="highlight p-4 bg-white rounded-lg shadow">
                        <h4 class="heading text-lg font-semibold mb-3 text-gray-800">元空间</h4>
                        <p class="text-gray-600">在JDK1.8中元空间区取代了永久代，永久代原本主要存放Class和Meta的信息。而元空间的本质和永久代类似，都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于：元空间并不在虚拟机中，而是使用本地内存。</p>
                    </div>
                    <div class="highlight p-4 bg-white rounded-lg shadow">
                        <h4 class="heading text-lg font-semibold mb-3 text-gray-800">直接内存</h4>
                        <p class="text-gray-600">直接内存不是虚拟机运行时数据区的一部分也不是Java虚拟机规范中定义的内存区域，而是使用的本地内存，该区域不受堆大小限制但是会受到本机总内存大小等限制。</p>
                    </div>
                </div>
            </div>
            
            <div class="mb-12">
                <h3 class="heading text-2xl font-semibold mb-4 text-gray-800">Java内存模型</h3>
                <img src="https://cdn.nlark.com/yuque/0/2022/png/21449790/1654432779028-b0d6224f-0955-4ad0-8768-7abd7b0e11ce.png" alt="Java内存模型" class="rounded-lg shadow-md w-full">
                <p class="mt-4 text-gray-600">在多线程的情况每个线程共享堆和方法区，所以就会出现线程不安全的问题。</p>
            </div>
        </section>

        <!-- JVM Runtime Parameters Section -->
        <section class="mb-16">
            <h2 class="heading text-3xl font-bold mb-8 text-gray-800">JVM运行时参数</h2>
            <img src="https://cdn.nlark.com/yuque/0/2022/png/21449790/1654432779331-ce449653-b681-46ed-ae2b-b360aca34a79.png" alt="JVM运行时参数" class="rounded-lg shadow-md w-full mb-8">
            
            <div class="code-block p-6 rounded-lg">
                <pre class="text-sm md:text-base overflow-x-auto"><code class="text-gray-200">
-server                                             ## 服务器模式
-Xms2g                                              ## 初始化堆内存大小
-Xmx2g                                              ## 堆内存最大值
-Xmn256m                                            ## 年轻代内存大小，整个JVM内存=年轻代 + 年老代 + 持久代
-Xss256k                                            ## 设置每个线程的堆栈大小
-XX:PermSize=256m                                   ## 持久代内存大小
-XX:MaxPermSize=256m                                ## 最大持久代内存大小
-XX:ReservedCodeCacheSize=256m                      ## 代码缓存，存储已编译方法生成的本地代码
-XX:+UseCodeCacheFlushing                           ## 代码缓存满时，让JVM放弃一些编译代码
-XX:+DisableExplicitGC                              ## 忽略手动调用GC, System.gc()的调用就会变成一个空调用，完全不触发GC
-Xnoclassgc                                         ## 禁用类的垃圾回收，性能会高一点
-XX:+UseConcMarkSweepGC                             ## 并发标记清除（CMS）收集器
-XX:+CMSParallelRemarkEnabled                       ## 启用并行标记，降低标记停顿
-XX:+UseParNewGC                                    ## 对年轻代采用多线程并行回收，这样收得快
-XX:+UseCMSCompactAtFullCollection                  ## 在FULL GC的时候对年老代的压缩，Full GC后会进行内存碎片整理，过程无法并发，空间碎片问题没有了，但提顿时间不得不变长了
-XX:CMSFullGCsBeforeCompaction=3                    ## 多少次Full GC 后压缩old generation一次
-XX:LargePageSizeInBytes=128m                       ## 内存页的大小
-XX:+UseFastAccessorMethods                         ## 原始类型的快速优化
-XX:+UseCMSInitiatingOccupancyOnly                  ## 使用设定的回收阈值(下面指定的70%)开始CMS收集,如果不指定,JVM仅在第一次使用设定值,后续则自动调整
-XX:CMSInitiatingOccupancyFraction=70               ## 使用cms作为垃圾回收使用70％后开始CMS收集
-XX:SoftRefLRUPolicyMSPerMB=50                      ## Soft reference清除频率，默认存活1s,设置为0就是不用就清除
-XX:+AlwaysPreTouch                                 ## 强制操作系统把内存真正分配给JVM
-XX:+PrintClassHistogram                            ## 按下Ctrl+Break后，打印类的信息
-XX:+PrintGCDetails                                 ## 输出GC详细日志
-XX:+PrintGCTimeStamps                              ## 输出GC的时间戳（以基准时间的形式）
-XX:+PrintHeapAtGC                                  ## 在进行GC的前后打印出堆的信息
-XX:+PrintGCApplicationConcurrentTime               ## 输出GC之间运行了多少时间
-XX:+PrintTenuringDistribution                      ## 参数观察各个Age的对象总大小
-XX:+PrintGCApplicationStoppedTime                  ## GC造成应用暂停的时间
-Xloggc:../log/gc.log                               ## 指定GC日志文件的输出路径
-ea                                                 ## 打开断言机制，jvm默认关闭
-Dsun.io.useCanonCaches=false                       ## java_home没有配置，或配置错误会报异常
-Dsun.awt.keepWorkingSetOnMinimize=true             ## 可以让IDEA最小化到任务栏时依然保持以占有的内存，当你重新回到IDEA，能够被快速显示，而不是由灰白的界面逐渐显现整个界面，加快回复到原界面的速度
-Djava.net.preferIPv4Stack=true                     ## 让tomcat默认使用IPv4
-Djdk.http.auth.tunneling.disabledSchemes=""        ## 等于Basic会禁止proxy使用用户名密码这种鉴权方式,反之空就可以使用
-Djsse.enablesSNIExtension=false                    ## SNI支持，默认开启，开启会造成ssl握手警告
-XX:+HeapDumpOnOutOfMemoryError                     ## 表示当JVM发生OOM时，自动生成DUMP文件
-XX:HeapDumpPath=D:/data/log                        ## 表示生成DUMP文件的路径，也可以指定文件名称，如果不指定文件名，默认为：java_<pid>_<date>_<time>_heapDump.hprof。  
-XX:-OmitStackTraceInFastThrow                      ## 省略异常栈信息从而快速抛出,这个配置抛出这个异常非常快，不用额外分配内存，也不用爬栈,但是出问题看不到stack trace，不利于排查问题
-Dfile.encoding=UTF-8
-Duser.name=toString
-XX:ParallelGCThreads：                             ## 设置垃圾回收并行线程的数量。
-XX:ConcGCThreads：                                 ## 设置并发垃圾回收线程的数量。
-XX:+UseG1GC：                                      ## 启用G1垃圾回收器。
-XX:+UseParallelGC：                                ## 启用并行垃圾回收器。
-XX:+UseSerialGC：                                  ## 启用串行垃圾回收器。
                </code></pre>
            </div>
        </section>

        <!-- Class Loading Process Section -->
        <section class="mb-16">
            <h2 class="heading text-3xl font-bold mb-8 text-gray-800">类加载过程</h2>
            <img src="https://cdn.nlark.com/yuque/0/2022/png/21449790/1660452952000-65bda564-41cb-43f2-9169-c9855507a7c0.png" alt="类加载过程" class="rounded-lg shadow-md w-full mb-8">
            <p class="text-gray-600 mb-6">java文件通过编译器变成了.class文件，接下来类加载器又将这些.class文件加载到JVM中。其实可以一句话来解释：类的加载指的是将类的.class文件中的二进制数据读入到内存中，将其放在运行时数据区的方法区内，然后在堆区创建一个 java.lang.Class对象，用来封装类在方法区内的数据结构。</p>
            
            <div class="mb-8">
                <h3 class="heading text-2xl font-semibold mb-4 text-gray-800">类加载初始化的时间</h3>
                <p class="text-gray-600 mb-4">只有当对类的主动使用的时候才会导致类的初始化，类的主动使用包括以下六种：</p>
                <ul class="list-disc pl-6 text-gray-600 space-y-2">
                    <li>创建类的实例，也就是new的方式</li>
                    <li>访问某个类或接口的静态变量，或者对该静态变量赋值</li>
                    <li>调用类的静态方法</li>
                    <li>反射（如Class.forName("com.ts.Demo")）</li>
                    <li>初始化某个类的子类，则其父类也会被初始化</li>
                    <li>Java虚拟机启动时被标明为启动类的类（Java Test），直接使用java.exe命令来运行某个主类</li>
                </ul>
            </div>
            
            <div>
                <h3 class="heading text-2xl font-semibold mb-4 text-gray-800">JVM组成部分</h3>
                <img src="https://cdn.nlark.com/yuque/0/2022/png/21449790/1660453266296-822bcd44-322a-4314-8780-48b277344f90.png" alt="JVM组成部分" class="rounded-lg shadow-md w-full mb-6">
                <p class="text-gray-600 mb-4">JVM包含两个子系统和两个组件，两个子系统为Class loader(类装载)、Execution engine(执行引擎)；两个组件为Runtime data area(运行时数据区)、Native Interface(本地接口)。</p>
                
                <div class="grid md:grid-cols-2 gap-6">
                    <div class="bg-white p-6 rounded-lg shadow">
                        <h4 class="heading text-lg font-semibold mb-3 text-gray-800">Class loader(类装载)</h4>
                        <p class="text-gray-600">根据给定的全限定名类名(如：java.lang.Object)来装载class文件到Runtime data area中的method area。</p>
                    </div>
                    <div class="bg-white p-6 rounded-lg shadow">
                        <h4 class="heading text-lg font-semibold mb-3 text-gray-800">Execution engine（执行引擎）</h4>
                        <p class="text-gray-600">执行classes中的指令。</p>
                    </div>
                    <div class="bg-white p-6 rounded-lg shadow">
                        <h4 class="heading text-lg font-semibold mb-3 text-gray-800">Native Interface(本地接口)</h4>
                        <p class="text-gray-600">与native libraries交互，是其它编程语言交互的接口。</p>
                    </div>
                    <div class="bg-white p-6 rounded-lg shadow">
                        <h4 class="heading text-lg font-semibold mb-3 text-gray-800">Runtime data area(运行时数据区域)</h4>
                        <p class="text-gray-600">这就是我们常说的JVM的内存。</p>
                    </div>
                </div>
                
                <p class="mt-6 text-gray-600">首先通过编译器把 Java 代码转换成字节码，类加载器（ClassLoader）再把字节码加载到内存中，将其放在运行时数据区（Runtime data area）的方法区内，而字节码文件只是 JVM 的一套指令集规范，并不能直接交给底层操作系统去执行，因此需要特定的命令解析器执行引擎（Execution Engine），将字节码翻译成底层系统指令，再交由 CPU 去执行，而这个过程中需要调用其他语言的本地库接口（Native Interface）来实现整个程序的功能。</p>
            </div>
        </section>

        <!-- Class Loader Section -->
        <section class="mb-16">
            <h2 class="heading text-3xl font-bold mb-8 text-gray-800">类加载器</h2>
            <p class="text-gray-600 mb-6">一个Java文件从编码完成到最终执行，一般主要包括两个过程：编译和运行，其中编译就是把我们写好的java文件，通过javac命令编译成字节码，也就是我们常说的.class文件，然后运行则是把编译生成的.class文件交给Java虚拟机(JVM)执行。而我们所说的<strong>类加载过程即是指JVM虚拟机把.class文件中类信息加载进内存，并进行解析生成对应的class对象的过程</strong>。</p>
            <p class="text-gray-600 mb-8">举个通俗点的例子来说，JVM在执行某段代码时，遇到了class A， 然而此时内存中并没有class A的相关信息，于是JVM就会到相应的class文件中去寻找class A的类信息，并加载进内存中，这就是我们所说的类加载过程。由此可见，JVM不是一开始就把所有的类都加载进内存中，而是只有第一次遇到某个需要运行的类时才会加载，且只加载一次。</p>
            
            <div class="mb-8">
                <h3 class="heading text-2xl font-semibold mb-4 text-gray-800">对象/类/类加载器</h3>
                <div class="grid md:grid-cols-2 gap-6">
                    <div class="code-block p-6 rounded-lg">
                        <pre class="text-sm md:text-base overflow-x-auto"><code class="text-gray-200">
// 实例化三个对象
User user1 = new User();
User user2 = new User();
User user3 = new User();

// 输出内存地址
System.out.println(user1);
System.out.println(user2);
System.out.println(user3);

// 获取3个类的类对象
System.out.println(user1.getClass().hashCode());
System.out.println(user2.getClass().hashCode());
System.out.println(user3.getClass().hashCode());

// 获取类加载器
System.out.println(user1.getClass().getClassLoader());
System.out.println(user2.getClass().getClassLoader());
System.out.println(user3.getClass().getClassLoader());
                        </code></pre>
                    </div>
                    <div class="code-block p-6 rounded-lg">
                        <pre class="text-sm md:text-base overflow-x-auto"><code class="text-gray-200">
// 对象
user1:com.qf.entity.User@78308db1
user2:com.qf.entity.User@27c170f0
user3:com.qf.entity.User@5451c3a8
// 类对象
user1:1229416514
user2:1229416514
user3:1229416514
// 类加载器
user1:sun.misc.Launcher$AppClassLoader@18b4aac2
user2:sun.misc.Launcher$AppClassLoader@18b4aac2
user3:sun.misc.Launcher$AppClassLoader@18b4aac2
                        </code></pre>
                    </div>
                </div>
            </div>
            
            <div class="mb-8">
                <h3 class="heading text-2xl font-semibold mb-4 text-gray-800">类加载器类型</h3>
                <div class="grid md:grid-cols-3 gap-6">
                    <div class="bg-white p-6 rounded-lg shadow">
                        <h4 class="heading text-lg font-semibold mb-3 text-gray-800">启动(Bootstrap)类加载器</h4>
                        <p class="text-gray-600">启动类加载器是用本地代码实现的类加载器，它负责将JAVA_HOME/lib下面的核心类库或-Xbootclasspath选项指定的jar包等虚拟机识别的类库加载到内存中。</p>
                    </div>
                    <div class="bg-white p-6 rounded-lg shadow">
                        <h4 class="heading text-lg font-semibold mb-3 text-gray-800">扩展(Extension)类加载器</h4>
                        <p class="text-gray-600">扩展类加载器是由Sun的ExtClassLoader（sun.misc.Launcher$ExtClassLoader）实现的，它负责将JAVA_HOME /jre/lib/ext或者由系统变量-Djava.ext.dir指定位置中的类库加载到内存中。</p>
                    </div>
                    <div class="bg-white p-6 rounded-lg shadow">
                        <h4 class="heading text-lg font-semibold mb-3 text-gray-800">系统(System)类加载器</h4>
                        <p class="text-gray-600">系统类加载器是由 Sun 的 AppClassLoader（sun.misc.Launcher$AppClassLoader）实现的，它负责将用户类路径(即当前类所在路径及其引用的第三方类库的路径)下的类库加载到内存中。</p>
                    </div>
                </div>
            </div>
            
            <div>
                <h3 class="heading text-2xl font-semibold mb-4 text-gray-800">双亲委派机制</h3>
                <p class="text-gray-600 mb-6">双亲委派机制是当类加载器需要加载某一个.class字节码文件时，则首先会把这个任务委托给他的上级类加载器，递归这个操作，如果上级没有加载该.class文件，自己才会去加载这个.class，如果自己也也加载不到就抛出Class Not Found异常。</p>
                <img src="https://cdn.nlark.com/yuque/0/2022/png/21449790/1654432780260-c8c14bce-305d-420b-9c45-42d27897b268.png" alt="双亲委派机制" class="rounded-lg shadow-md w-full mb-6">
                
                <div class="mb-6">
                    <h4 class="heading text-xl font-semibold mb-3 text-gray-800">对双亲委派机制的理解</h4>
                    <p class="text-gray-600 mb-4"><strong>双：</strong>代表是两两的意思。<strong>亲：</strong>代表两者之间有着关系。<strong>委派：</strong>则是我们个人办不到的事情，委托别人去帮我们完成的一致<strong>机制</strong>。</p>
                    <p class="text-gray-600">总体来说，就是当一个类加载的时候首先会委托给上级类加载器去加载，当父加载器说这不是我做的事情时，则该任务又会落回到子加载器，此时只有子加载器自己完成该事情。</p>
                </div>
                
                <div>
                    <h4 class="heading text-xl font-semibold mb-3 text-gray-800">双亲委派机制的好处</h4>
                    <ul class="list-disc pl-6 text-gray-600 space-y-2">
                        <li>向上委托给父类加载，父类加载不了再自己加载</li>
                        <li>避免重复加载，防止Java核心api被篡改</li>
                    </ul>
                </div>
            </div>
        </section>

        <!-- Memory Leak Section -->
        <section class="mb-16">
            <h2 class="heading text-3xl font-bold mb-8 text-gray-800">内存泄露</h2>
            
            <div class="mb-8">
                <h3 class="heading text-2xl font-semibold mb-4 text-gray-800">什么是内存泄露</h3>
                <p class="text-gray-600">内存泄露也称作"存储渗漏"，用动态存储分配函数动态开辟的空间，<strong>在使用完毕后未释放，结果导致一直占据该内存单元。直到程序结束</strong>。(其实说白了就是该内存空间使用完毕之后未回收即所谓内存泄漏)。</p>
            </div>
            
            <div>
                <h3 class="heading text-2xl font-semibold mb-4 text-gray-800">常见的内存泄露</h3>
                <ul class="list-disc pl-6 text-gray-600 space-y-2">
                    <li>资源中没有及时释放，导致GC无法回收。</li>
                    <li>资源未关闭造成的内存泄漏</li>
                    <li>全局缓存持有的对象不使用的时候没有及时移除，导致一直在内存中无法移除(比如单例的生命周期和应用的生命周期一样)</li>
                    <li>静态类的集合生命周期长的对象持有短生命周期对象的引用，尽管短生命周期的对象不再使用，但是因为长生命周期对象持有它的引用而导致不能被回收。</li>
                    <li>释放了内存却继续使用它</li>
                    <li>该对象已经没有使用了(强引用)，但是没有被gc回收</li>
                </ul>
            </div>
        </section>

        <!-- Memory Overflow Section -->
        <section class="mb-16">
            <h2 class="heading text-3xl font-bold mb-8 text-gray-800">内存溢出</h2>
            
            <div class="mb-8">
                <h3 class="heading text-2xl font-semibold mb-4 text-gray-800">什么是内存溢出</h3>
                <p class="text-gray-600">内存溢出OOM( out of memory)，<strong>是指程序在申请内存时没有足够的内存空间供其使用</strong>，出现out of memory；比如申请了一个integer,但给它存了long才能存下的数，那就是内存溢出。内存溢出就是你要求分配的内存超出了系统能给你的，系统不能满足需求，于是产生溢出。</p>
            </div>
            
            <div class="mb-8">
                <h3 class="heading text-2xl font-semibold mb-4 text-gray-800">内存溢出的原因</h3>
                <p class="text-gray-600">编写java程序最为方便的地方就是我们不需要管理内存的分配和释放，一切由jvm来进行处理，当java对象不再被引用时，等到堆内存不够用时，jvm会进行垃圾回收，清除这些对象占用的堆内存空间，如果对象一直被引用，jvm无法对其进行回收，创建新的对象时，无法从Heap中获取足够的内存分配给对象，这时候就会导致内存溢出。而出现内存溢出的地方，一般是不断的往容器中存放对象，而容器没有相应的大小限制或清除机制。容易导致内存溢出。</p>
            </div>
            
            <div>
                <h3 class="heading text-2xl font-semibold mb-4 text-gray-800">内存溢出的场景</h3>
                <ul class="list-disc pl-6 text-gray-600 space-y-2">
                    <li>递归</li>
                    <li>内存空间不够时，还在申请内存空间。</li>
                </ul>
            </div>
        </section>

        <!-- Heap Area Section -->
        <section class="mb-16">
            <h2 class="heading text-3xl font-bold mb-8 text-gray-800">堆区</h2>
            <p class="text-gray-600 mb-6">在JVM中，堆区是重中之重。栈区是不会有垃圾回收的，所以经常说的垃圾回收，其实就是回收的是堆区(Heap)的数据。在这里我们会讲到，新生代、老年代、永久代(元空间)。</p>
            <p class="text-gray-600 mb-8">堆内存主要分文以下三部分：</p>
            
            <div class="grid md:grid-cols-3 gap-6 mb-8">
                <div class="bg-white p-6 rounded-lg shadow">
                    <h4 class="heading text-lg font-semibold mb-3 text-gray-800">Young Generation Space</h4>
                    <p class="text-gray-600">新生区Young/New</p>
                </div>
                <div class="bg-white p-6 rounded-lg shadow">
                    <h4 class="heading text-lg font-semibold mb-3 text-gray-800">Tenure generation space</h4>
                    <p class="text-gray-600">老年代Old/Tenure</p>
                </div>
                <div class="bg-white p-6 rounded-lg shadow">
                    <h4 class="heading text-lg font-semibold mb-3 text-gray-800">Permanent space</h4>
                    <p class="text-gray-600">永久区/元空间Perm</p>
                </div>
            </div>
            
            <div class="mb-8">
                <img src="https://cdn.nlark.com/yuque/0/2022/png/21449790/1654432780765-7c7dd45e-5fa5-4954-8a97-3809644d2909.png" alt="